package fibonacci

import (
	"fmt"
	"math"
	"time"
)

// Menu ,实验一菜单
func Menu() {
	flag := true
	for flag {
		printDirectory()
		var number int
		_, err := fmt.Scan(&number)
		if err != nil {
			return
		}

		switch number {
		case 1:
			var num int64
			fmt.Println("请输入一个数字n: ")
			_, err := fmt.Scan(&num)
			if err != nil {
				fmt.Println(err)
				return
			}

			fmt.Println("==========================================================")
			fmt.Printf("          1、用五种方法计算第%d个斐波那契数列           \n", num)
			fmt.Println("----------------------------------------------------------")
			fmt.Println("使用方法    斐波那契数  基本操作 执行时间 空间效率 操作次数")
			fmt.Println("==========================================================")
			// 迭代法
			begin := time.Now()
			num1, count1 := Iterate(num)
			t := time.Since(begin).Seconds()
			fmt.Printf("迭代法      %d   加法   %f   线性   %d\n", num1, t, count1)
			// 迭代改进法
			begin = time.Now()
			num3, count3 := ImprovedIterative(num)
			t = time.Since(begin).Seconds()
			fmt.Printf("迭代改进法  %d   加法   %f   常数   %d\n", num3, t, count3)
			// 公式法
			begin = time.Now()
			num2 := Formula(num)
			t = time.Since(begin).Seconds()
			fmt.Printf("公式法      %d   乘法   %f   线性   4\n", num2, t)
			// 递归法
			begin = time.Now()
			num4 := Recursion(num)
			t = time.Since(begin).Seconds()
			fmt.Printf("递归法      %d   加法   %f   指数   %d\n", num4, t, count4)
			// 矩阵法
			begin = time.Now()
			num5 := Matrix(int(num))
			t = time.Since(begin).Seconds()
			fmt.Printf("矩阵法      %d   加法   %f   线性   %d\n", num5, t, count5)
		case 2:
			begin := time.Now()
			fmt.Printf("迭代算法 : %d\n", Iterate2())
			t := time.Since(begin).Seconds()
			fmt.Println("使用时间:", t)
		case 3:
			begin := time.Now()
			var pre int32
			pre = 1
			for i := 1; i <= math.MaxInt16; i++ {
				number := Recursion2(int32(i))
				if pre > number {
					fmt.Printf("递归算法: %d\n", i-1)
					break
				}
				pre = number
			}
			t := time.Since(begin).Seconds()
			fmt.Println("使用时间:", t)
		case 4:
			n := Iterate2()
			begin := time.Now()
			Recursion(int64(n))
			t := time.Since(begin).Seconds()
			fmt.Println("使用时间:", t)
			if t <= 60 {
				fmt.Println("可以")
			} else {
				fmt.Println("不可以")
			}
		case 5:

			num := 0
			var preT float64 = 0
			var currT float64 = 0
			var number1 int64
			for i := 0; i < math.MaxInt64; i++ {
				var t float64
				t = 0
				preT = t
				begin := time.Now()
				number1 = Recursion(int64(i))
				t = time.Since(begin).Seconds()
				currT = t
				if t > 30 {
					num = i - 1
					break
				}
			}
			fmt.Println("===========================================================")
			fmt.Println("    5、计算计算机能够在30秒内计算出的最大斐波那契数是第几个     ")
			fmt.Println("----------------------------------------------------------")
			fmt.Println("使用方法   第X个   斐波那契数  计算出下一个斐波那契数的时间")
			fmt.Println("===========================================================")
			fmt.Printf("递归法   %d   %d    %f\n", num, number1, currT-preT)

			num2 := 0
			preT = 0
			currT = 0
			var number2 int64
			for j := 0; j < math.MaxInt64; j++ {
				var t float64
				t = 0
				preT = t
				begin := time.Now()
				number2 = int64(Iterate3(int64(j)))
				t = time.Since(begin).Seconds()
				currT = t
				if t > 30 {
					num2 = j - 1
					break
				}
				break
			}
			fmt.Printf("迭代法   %d   %d    %f\n", num2, number2, currT-preT)
		case 6:

			for i := 0; i < math.MaxInt64; i++ {
				number1 := Iterate3(int64(i))
				number2 := math.Round(Formula(int64(i)))
				fmt.Println(number1, "=", number2)
				if number1 != number2 {
					fmt.Println(number1, "!=", number2)
					fmt.Println("最小n值: ", i)
					break
				}
			}

		case 0:
			flag = false
			break
		default:
			fmt.Println("请输入正确的数字!")
		}
	}
}

func printDirectory() {
	fmt.Println("-----------\n----------请输入相应数字执行相应方法:")
	fmt.Printf("----------1. 用五种方法计算斐波那契数列，且比较这五种方法的基本操作、基本操作次数、执行时间，以掌握对数、线性和指数增长率的极大差别\n" +
		"----------2. 使用 迭代法 计算能够支持的最大整数的斐波那契数是第几个斐波那契数\n" +
		"----------3. 使用 递归法 计算能够支持的最大整数的斐波那契数是第几个斐波那契数\n" +
		"----------4. 编程环境能够支持的最大整数的斐波使用递归是否可以在1分钟内完成\n" +
		"----------5. 计算计算机能够在30秒内计算出的最大斐波那契数是第几个？\n" +
		"----------6. 利用公式计算第n个斐波那契数,找出出现误差时的最小n值\n" +
		"----------0. 退出程序\n----------")
}
